#include <pthread.h>
#include <errno.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include "ptwrap.hpp"

// [[ex02db]]
// DEBUG descr Sleeplock.
class sleepmutex
{
public:
	sleepmutex() :
		locked_(false)
	{ }

	int lock()
	{
		pw::lockmutex lm(cond_);
		while(locked_)
			cond_.wait();
		locked_ = true;
		return 0;
	}
	int trylock()
	{
		pw::lockmutex lm(cond_);
		if (locked_)
			return ETIMEDOUT;
		locked_ = true;
		return 0;
	}
	int unlock()
	{
		pw::lockmutex lm(cond_);
		locked_ = false;
		cond_.signal();
	}

protected:
	pw::pmcond cond_; // both condition variable and mutex
	bool locked_; // flag: this mutex is locked
};
// END

// DEBUG
sleepmutex m;

class try_thread : public pw::pwthread
{
public:
	void *execute()
	{
		if (m.trylock() == 0) {
			fprintf(stderr, "%p: trylock succeeded\n", get_id());
		} else {
			fprintf(stderr, "%p: trylock failed\n", get_id());
			m.lock();
			fprintf(stderr, "%p: locked\n", get_id());
		}
		sleep(1);
		fprintf(stderr, "%p: unlocking\n", get_id());
		m.unlock();

		return 0;
	}

};

int main()
{
	try_thread t1, t2;
	t1.start(); t2.start();
	t1.join(); t2.join();
	fprintf(stderr, "Done.\n");

	return 0;
}

/*
A sample output:

0x7f0f8c92d910: trylock succeeded
0x7f0f8bf2c910: trylock failed
0x7f0f8c92d910: unlocking
0x7f0f8bf2c910: locked
0x7f0f8bf2c910: unlocking
Done.
*/
